package AgentTravel.Behaviours;

import java.io.IOException;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import AgentTravel.LogicObjects.DayPlan;
import AgentTravel.LogicObjects.DayPlanBusy;
import AgentTravel.LogicObjects.DayPlanFree;
import AgentTravel.LogicObjects.DayPlanReserved;
import AgentTravel.LogicObjects.DayPlanTravelling;
import AgentTravel.LogicObjects.UserInfoForServer;
import AgentTravel.LogicObjects.UserProfile;
import AgentTravel.Messages.DayGuestMessage;
import AgentTravel.Messages.NewDayPlanMessage;
import AgentTravel.Messages.RejectVisitMessage;
import jade.core.AID;
import jade.core.behaviours.CyclicBehaviour;
import jade.lang.acl.ACLMessage;
import jade.lang.acl.MessageTemplate;
import jade.lang.acl.UnreadableException;
import jade.wrapper.StaleProxyException;

public class ServerAnswerQuestions extends CyclicBehaviour
{

	private Map<String,UserInfoForServer> users;
	private Map<String,String> passLogin;
	private Map<String,AID> userGui;
	
	public ServerAnswerQuestions(Map<String, UserInfoForServer> users2,Map<String, String> passLogin2,Map <String,AID> userGui)
	{
		this.users=users2;
		this.passLogin=passLogin2;
		this.userGui=userGui;
	}
	
	@Override
	public void action() 
	{
		MessageTemplate mt=MessageTemplate.MatchPerformative(ACLMessage.QUERY_IF);
		mt=MessageTemplate.or(mt, MessageTemplate.MatchPerformative(ACLMessage.PROPAGATE));
		mt=MessageTemplate.or(mt,MessageTemplate.MatchPerformative(ACLMessage.REJECT_PROPOSAL));
		
		ACLMessage msg = myAgent.receive(mt);
		if(msg!=null)
		{
			if(msg.getPerformative()==ACLMessage.PROPAGATE)
			{
				System.out.println("SERWER: visitor planuje wyjazd");
				try 
				{
					Iterator<String> iter= users.keySet().iterator();
					while(iter.hasNext())
					{
						String s=iter.next();
						if(users.get(s).yourVisitorAgent.getName().equals(msg.getSender().getName()))
						{
							if(userGui.containsKey(s))
							{
								ACLMessage info=new ACLMessage(ACLMessage.INFORM_REF);
								info.addReceiver(userGui.get(s));
								info.setContentObject(msg.getContentObject());
								System.out.println("SERWER: wysylam planowanie do gui");
								myAgent.send(info);
							}
							break;
						}
					}
					
				} 
				catch (UnreadableException e) 
				{
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (StaleProxyException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			else if(msg.getPerformative()==ACLMessage.REJECT_PROPOSAL)
			{
				//dostalem odwolanie wizyty
				RejectVisitMessage rvm;
				
				try 
				{
					rvm=(RejectVisitMessage)msg.getContentObject();
						Iterator<String> iter= users.keySet().iterator();
						while(iter.hasNext())
						{
							String s=iter.next();
							if(users.get(s).yourVisitorAgent.getName().equals(msg.getSender().getName()))
							{
								if(users.get(s).yourUserInfo.getCalendar().GetDayPlan(rvm.day) instanceof DayPlanReserved)
								{
									DayPlanReserved dpr=(DayPlanReserved)users.get(s).yourUserInfo.getCalendar().GetDayPlan(rvm.day);
									//zaktualizowanie kalendarza
									if(dpr.getGuests().contains(rvm.profile))
									{
										dpr.getGuests().remove(rvm.profile);
										if(dpr.getGuests().size()==0)
											users.get(s).yourUserInfo.getCalendar().SetDayPlan(rvm.day, new DayPlanFree());
										
										if(userGui.containsKey(s))
										{
											ACLMessage toGui=new ACLMessage(ACLMessage.INFORM_REF);
											toGui.addReceiver(userGui.get(s));
											toGui.setContentObject(new NewDayPlanMessage(rvm.day,
													users.get(s).yourUserInfo.getCalendar().GetDayPlan(rvm.day)));
											System.out.println("SERWER wysyla aktualizacje do"+userGui.get(s).getName());
											myAgent.send(toGui);
										}
									}
								}
						}
					}
				} 
					catch (UnreadableException e) 
				{
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					} catch (StaleProxyException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			else if(msg.getPerformative()==ACLMessage.QUERY_IF)
			{
				System.out.println("SERWER: dostalem pytanie o dostepnosc dnia");
				DayGuestMessage dgm=null;
				
				try 
				{
					dgm=(DayGuestMessage)msg.getContentObject();
		
					String guestLogin="";
					boolean any=false;
					Iterator<String> itv= users.keySet().iterator();
					while(itv.hasNext())
					{
						String s = itv.next();
						if(users.get(s).yourUserInfo.getProfile().getFullName().equals(dgm.guest.getFullName()))
						{
							guestLogin=s;
							any=true;
							break;
						}
					}
					if(!any)
						System.out.println("SERWER: nie ma takiego goscia");
					
					
					AID sender=msg.getSender();
					Iterator<String> iter = users.keySet().iterator();
					while(iter.hasNext())
					{
						String userString=iter.next();
						UserInfoForServer info=users.get(userString);
						try 
						{
							if(info.yourHostAgent.getName().equals(sender.getName()))
							{
								DayPlan dp = info.yourUserInfo.getCalendar().GetDayPlan(dgm.day);
								if(dp instanceof DayPlanFree || 
										((dp instanceof DayPlanReserved) && 
												((DayPlanReserved)dp).getGuests().size()<
												info.yourUserInfo.getProfile().getBedsCount()))
								{
									System.out.println("SERWER: informuje ze mozna przyjac goscia");
						
									//zaktualizowanie danych hosta
									DayPlanReserved plan=new DayPlanReserved();
									
									if(dp instanceof DayPlanReserved)
									{
										DayPlanReserved prev=(DayPlanReserved)dp;
										plan.getGuests().addAll(prev.getGuests());
									}
									plan.getGuests().add(dgm.guest);
									
									info.yourUserInfo.getCalendar().SetDayPlan(dgm.day, plan);
									//potwierdzenie dla Guihosta
									if(userGui.containsKey(userString))
									{
										ACLMessage toHostGui=new ACLMessage(ACLMessage.INFORM_REF);
										toHostGui.addReceiver(userGui.get(userString));
										toHostGui.setContentObject(new NewDayPlanMessage(dgm.day, plan));
										System.out.println("SERWER wysyla aktualizacje do"+userGui.get(userString).getName());
										myAgent.send(toHostGui);
									}
	
									//zaktualizowanie danych goscia
									
									users.get(guestLogin).yourUserInfo.getCalendar().SetDayPlan(dgm.day, 
											new DayPlanTravelling(info.yourUserInfo.getProfile().getCity(),info.yourUserInfo.getProfile()));
									
									//potwierdzenie dla GuiGoscia
									
									if(userGui.containsKey(guestLogin))
									{
										ACLMessage toGuestGui=new ACLMessage(ACLMessage.INFORM_REF);
										toGuestGui.addReceiver(userGui.get(guestLogin));
										toGuestGui.setContentObject(new NewDayPlanMessage(dgm.day,
												users.get(guestLogin).yourUserInfo.getCalendar().GetDayPlan(dgm.day)));
										System.out.println("SERWER wysyla aktualizacje do"+userGui.get(guestLogin).getName());
										myAgent.send(toGuestGui);
									}
									
									
									
									//potwierdzenie dla hostAgenta
									ACLMessage reply=new ACLMessage(ACLMessage.CONFIRM);
									reply.addReceiver(sender);
									reply.setContentObject(dgm.day);
									myAgent.send(reply);
																
								}
								else
								{
									System.out.println("Serwer: nie przyjmiemy tego goscia!");
									ACLMessage reply=new ACLMessage(ACLMessage.DISCONFIRM);
									reply.addReceiver(sender);
									reply.setContentObject(dgm.day);
									myAgent.send(reply);
								}
							}
						} 
						catch (StaleProxyException e) 
						{
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
						catch (IOException e) 
						{
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}
				}
				catch (UnreadableException e1) 
				{
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
			}
		}
		else
			block();
	}

}
